package com.xiaoyung.easyisapisdk.common.util;

import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.xiaoyung.easyisapisdk.common.util.bean.BeanUtils;
import com.xiaoyung.easyisapisdk.common.util.text.StrFormatter;

/**
 * 字符串工具类
 * 
 * 
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils {
	/**
	 * UTF-8 字符集
	 */
	public static final String UTF8 = "UTF-8";

	/**
	 * GBK 字符集
	 */
	public static final String GBK = "GBK";

	/**
	 * RMI 远程方法调用
	 */
	public static final String LOOKUP_RMI = "rmi://";

	/**
	 * http请求
	 */
	public static final String HTTP = "http://";

	/**
	 * https请求
	 */
	public static final String HTTPS = "https://";

	
	
	
	/** 空字符串 */
	private static final String NULLSTR = "";

	/** 下划线 */
	private static final char SEPARATOR = '_';

	/**
	 * 获取参数不为空值
	 * 
	 * @param value defaultValue 要判断的value
	 * @return value 返回值
	 */
	public static <T> T nvl(T value, T defaultValue) {
		return value != null ? value : defaultValue;
	}

	/**
	 * * 判断一个Collection是否为空， 包含List，Set，Queue
	 * 
	 * @param coll 要判断的Collection
	 * @return true：为空 false：非空
	 */
	public static boolean isEmpty(Collection<?> coll) {
		return isNull(coll) || coll.isEmpty();
	}

	/**
	 * * 判断一个Collection是否非空，包含List，Set，Queue
	 * 
	 * @param coll 要判断的Collection
	 * @return true：非空 false：空
	 */
	public static boolean isNotEmpty(Collection<?> coll) {
		return !isEmpty(coll);
	}

	/**
	 * * 判断一个对象数组是否为空
	 * 
	 * @param objects 要判断的对象数组
	 ** @return true：为空 false：非空
	 */
	public static boolean isEmpty(Object[] objects) {
		return isNull(objects) || (objects.length == 0);
	}

	/**
	 * * 判断一个对象数组是否非空
	 * 
	 * @param objects 要判断的对象数组
	 * @return true：非空 false：空
	 */
	public static boolean isNotEmpty(Object[] objects) {
		return !isEmpty(objects);
	}

	/**
	 * * 判断一个Map是否为空
	 * 
	 * @param map 要判断的Map
	 * @return true：为空 false：非空
	 */
	public static boolean isEmpty(Map<?, ?> map) {
		return isNull(map) || map.isEmpty();
	}

	/**
	 * * 判断一个Map是否为空
	 * 
	 * @param map 要判断的Map
	 * @return true：非空 false：空
	 */
	public static boolean isNotEmpty(Map<?, ?> map) {
		return !isEmpty(map);
	}

	/**
	 * * 判断一个字符串是否为空串
	 * 
	 * @param str String
	 * @return true：为空 false：非空
	 */
	public static boolean isEmpty(String str) {
		return isNull(str) || NULLSTR.equals(str.trim());
	}

	/**
	 * * 判断一个字符串是否为非空串
	 * 
	 * @param str String
	 * @return true：非空串 false：空串
	 */
	public static boolean isNotEmpty(String str) {
		return !isEmpty(str);
	}

	/**
	 * * 判断一个对象是否为空
	 * 
	 * @param object Object
	 * @return true：为空 false：非空
	 */
	public static boolean isNull(Object object) {
		return object == null;
	}

	/**
	 * * 判断一个对象是否非空
	 * 
	 * @param object Object
	 * @return true：非空 false：空
	 */
	public static boolean isNotNull(Object object) {
		return !isNull(object);
	}

	/**
	 * * 判断一个对象是否是数组类型（Java基本型别的数组）
	 * 
	 * @param object 对象
	 * @return true：是数组 false：不是数组
	 */
	public static boolean isArray(Object object) {
		return isNotNull(object) && object.getClass().isArray();
	}

	/**
	 * 去空格
	 */
	public static String trim(String str) {
		return (str == null ? "" : str.trim());
	}

	/**
	 * 截取字符串
	 * 
	 * @param str   字符串
	 * @param start 开始
	 * @return 结果
	 */
	public static String substring(final String str, int start) {
		if (str == null) {
			return NULLSTR;
		}

		if (start < 0) {
			start = str.length() + start;
		}

		if (start < 0) {
			start = 0;
		}
		if (start > str.length()) {
			return NULLSTR;
		}

		return str.substring(start);
	}

	/**
	 * 截取字符串
	 * 
	 * @param str   字符串
	 * @param start 开始
	 * @param end   结束
	 * @return 结果
	 */
	public static String substring(final String str, int start, int end) {
		if (str == null) {
			return NULLSTR;
		}

		if (end < 0) {
			end = str.length() + end;
		}
		if (start < 0) {
			start = str.length() + start;
		}

		if (end > str.length()) {
			end = str.length();
		}

		if (start > end) {
			return NULLSTR;
		}

		if (start < 0) {
			start = 0;
		}
		if (end < 0) {
			end = 0;
		}

		return str.substring(start, end);
	}

	/**
	 * 判断是否为空，并且不是空白字符
	 * 
	 * @param str 要判断的value
	 * @return 结果
	 */
	public static boolean hasText(String str) {
		return (str != null && !str.isEmpty() && containsText(str));
	}

	private static boolean containsText(CharSequence str) {
		int strLen = str.length();
		for (int i = 0; i < strLen; i++) {
			if (!Character.isWhitespace(str.charAt(i))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 格式化文本, {} 表示占位符<br>
	 * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
	 * 如果想输出 {} 使用 \\转义 { 即可，如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
	 * 例：<br>
	 * 通常使用：format("this is {} for {}", "a", "b") -> this is a for b<br>
	 * 转义{}： format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
	 * 转义\： format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
	 * 
	 * @param template 文本模板，被替换的部分用 {} 表示
	 * @param params   参数值
	 * @return 格式化后的文本
	 */
	public static String format(String template, Object... params) {
		if (isEmpty(params) || isEmpty(template)) {
			return template;
		}
		return StrFormatter.format(template, params);
	}

	/**
	 * 是否为http(s)://开头
	 * 
	 * @param link 链接
	 * @return 结果
	 */
	public static boolean ishttp(String link) {
		return StringUtils.startsWithAny(link, HTTP, HTTPS);
	}

	/**
	 * 驼峰转下划线命名
	 */
	public static String toUnderScoreCase(String str) {
		if (str == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		// 前置字符是否大写
		boolean preCharIsUpperCase = true;
		// 当前字符是否大写
		boolean curreCharIsUpperCase = true;
		// 下一字符是否大写
		boolean nexteCharIsUpperCase = true;
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (i > 0) {
				preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
			} else {
				preCharIsUpperCase = false;
			}

			curreCharIsUpperCase = Character.isUpperCase(c);

			if (i < (str.length() - 1)) {
				nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
			}

			if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) {
				sb.append(SEPARATOR);
			} else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) {
				sb.append(SEPARATOR);
			}
			sb.append(Character.toLowerCase(c));
		}

		return sb.toString();
	}

	/**
	 * 是否包含字符串
	 * 
	 * @param str  验证字符串
	 * @param strs 字符串组
	 * @return 包含返回true
	 */
	public static boolean inStringIgnoreCase(String str, String... strs) {
		if (str != null && strs != null) {
			for (String s : strs) {
				if (str.equalsIgnoreCase(trim(s))) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空，则返回空字符串。
	 * 例如：HELLO_WORLD->HelloWorld
	 * 
	 * @param name 转换前的下划线大写方式命名的字符串
	 * @return 转换后的驼峰式命名的字符串
	 */
	public static String convertToCamelCase(String name) {
		StringBuilder result = new StringBuilder();
		// 快速检查
		if (name == null || name.isEmpty()) {
			// 没必要转换
			return "";
		} else if (!name.contains("_")) {
			// 不含下划线，仅将首字母大写
			return name.substring(0, 1).toUpperCase() + name.substring(1);
		}
		// 用下划线将原始字符串分割
		String[] camels = name.split("_");
		for (String camel : camels) {
			// 跳过原始字符串中开头、结尾的下换线或双重下划线
			if (camel.isEmpty()) {
				continue;
			}
			// 首字母大写
			result.append(camel.substring(0, 1).toUpperCase());
			result.append(camel.substring(1).toLowerCase());
		}
		return result.toString();
	}

	/**
	 * 驼峰式命名法 例如：user_name->userName
	 */
	public static String toCamelCase(String s) {
		if (s == null) {
			return null;
		}
		s = s.toLowerCase();
		StringBuilder sb = new StringBuilder(s.length());
		boolean upperCase = false;
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);

			if (c == SEPARATOR) {
				upperCase = true;
			} else if (upperCase) {
				sb.append(Character.toUpperCase(c));
				upperCase = false;
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}

	
	// 下划线 驼峰互转换忽略 下划线开头的特殊处理 _cc_cc => _ccCc ; __aa_bb => __aaBb 
	public static String underLineCamelConvert(String key,boolean toCamel) {
		//有些特殊字段_orderId  __xxx,因此  _开头的不要转换
		String prefix = null;
		String undelineKey = key;
		if(key.startsWith("__")) {//好像没有这种
			//if(key.startsWith("_"));
			undelineKey = key.substring(2);
			prefix = "__";
		}else if(key.startsWith("_")) {
			undelineKey = key.substring(1);
			prefix = "_";
		}
		
		if((toCamel && undelineKey.indexOf("_")>-1) || (!toCamel) ) {
			String calmeKey = toCamel?StringUtils.underlineToCamel(undelineKey):StringUtils.camelToUnderline((undelineKey));
			if(prefix!=null) {
				calmeKey= prefix+calmeKey;
			} 
			return calmeKey;
		}
		return key;
		
	}
	/**
	 * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
	 * 
	 * @param str  指定字符串
	 * @param strs 需要检查的字符串数组
	 * @return 是否匹配
	 */
	/*public static boolean matches(String str, List<String> strs) {
		if (isEmpty(str) || isEmpty(strs)) {
			return false;
		}
		for (String pattern : strs) {
			if (isMatch(pattern, str)) {
				return true;
			}
		}
		return false;
	}
	*/
	/**
	 * 判断url是否与规则配置: ? 表示单个字符; * 表示一层路径内的任意字符串，不可跨层级; ** 表示任意层路径;
	 * 
	 * @param pattern 匹配规则
	 * @param url     需要匹配的url
	 * @return
	 */
	/*public static boolean isMatch(String pattern, String url) {
		AntPathMatcher matcher = new AntPathMatcher();
		return matcher.match(pattern, url);
	}*/

	@SuppressWarnings("unchecked")
	public static <T> T cast(Object obj) {
		return (T) obj;
	}
	
	private static Pattern keyPattern = Pattern.compile("\\$\\{.*?\\}");
	public static String fillTemplateParams(String content, Map<String, Object> params){
		if (params == null || params.isEmpty()) {
			return content;
		}
		Matcher m = keyPattern.matcher(content);
		while (m.find()) {
			String key = content.substring(m.start()+2, m.end()-1);
			Object value = null;
			try {
				value = BeanUtils.getProperty(params, key);
			} catch (Exception e) {
			
			}
			if (value == null) {
				value="";
				//throw new RuntimeException("缺少参数：" + key);
			}
			
			String before = content.substring(0, m.start());
			String after = content.substring(m.end(), content.length());
			//logger.debug("key:" + key + "\nvalue:" + value);
			content = before + value + after;
			m = keyPattern.matcher(content);
		}
		return content;
	}
	
	
	public static final String SOURCES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";

	/**
	 * Generate a random string.
	 *
	 * @param random     the random number generator.
	 * @param characters the characters for generating string.
	 * @param length     the length of the generated string.
	 * @return
	 */
	static public String generateString(Random random, String characters, int length) {
		char[] text = new char[length];
		for (int i = 0; i < length; i++) {
			text[i] = characters.charAt(random.nextInt(characters.length()));
		}
		return new String(text);
	}

	static public String generateString() {
		return generateString(new SecureRandom(), SOURCES, 40);
		// System.out.println(generateString(new Random(), SOURCES, 10));
		// System.out.println(generateString(new SecureRandom(), SOURCES, 15));
	}
	
	static public String generateString(Integer length) {
		return generateString(new SecureRandom(), SOURCES, length==null?40:length);
	}
	
	
	
	
	
	
	//10进制转换为英文字母表示的26进制
  	public static String to26Jinzhi(int data) {
  		String str = "abcdefghijklmnopqrstuvwxyz";
  		int scale = str.length(); //转化目标进制
          String s = "";
          if(data==0)
          {
          	return str.charAt(0)+"";
          }
          while(data > 0){
              if(data < scale){
                  s = str.charAt(data) + s;
                  data = 0;
              }else{
                  int r = data%scale;
                  s = str.charAt(r) + s;
                  data  = (data-r)/scale;
              }
          }
          return s;
  	}
  	/**
  	 * 26 转10进制
  	 * @param code
  	 * @return
  	 */
  	public static Integer to10From26(String code) {
  		Integer total=0;
  		for (int i = 0; i<code.length(); i++) {
  			int value=Integer.valueOf(Character.toLowerCase(code.charAt(i)))-97;
  			//A 65,B 66,a 97,b 98
  			total+=(int) (value*Math.pow(26,code.length()-i-1));
  			//System.out.println(value+"*26 "+(code.length()-i-1));
  			
		}
  		return total;
  	}
  	//BAA 是1 加-675是为了保证至少三位字母格式
  	
  	public static String getTableCodeByNum(int num) {//count 从1开始
  		return StringUtils.to26Jinzhi(675+num);//count=1 则676  对应BAA第一个表
  	}
  	public static int getTableNumByCode(String code) {
  		return StringUtils.to10From26(code)-675;
  	}
  	
	
	/**
     * 驼峰格式字符串转换为下划线格式字符串
     * 
     * @param param
     * @return
     */
    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(Character.toLowerCase(c));
            }
        }
        return sb.toString();
    }

    
    static final char UNDERLINE = '_';
    /**
     * 下划线格式字符串转换为驼峰格式字符串
     * 
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        
        //没有_就不用转换成驼峰模式
        if(param.indexOf("_")==-1) {
        	return param; 
        }
        
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (c == UNDERLINE) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            } else {
                sb.append(Character.toLowerCase(c));
            }
        }
        return sb.toString();
    }
    
  //首字母转小写
    public static String toLowerCaseFirstOne(String s){
      if(Character.isLowerCase(s.charAt(0)))
        return s;
      else
        return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    //首字母转大写
    public static String toUpperCaseFirstOne(String s){
      if(Character.isUpperCase(s.charAt(0)))
        return s;
      else
        return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }
    
    //将字符串中的 正则符号 转义
	public static String escapeRegex(String str) {
		if (str == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			switch (c) {
			case '.':
			case '*':
			case '+':
			case '?':
			case '|':
			case '(':
			case ')':
			case '[':
			case ']':
			case '{':
			case '}':
			case '^':
			case '$':
			case '\\':
				sb.append("\\").append(c);
				break;
			default:
				sb.append(c);
				break;
			}
		}
		return sb.toString();
	}
	
	public static Boolean sqlLikeMatch(String parttern,String str) {
		//+ "   if(new RegExp('^'+compareValueArr[i].replace(/%/gm,'.*').replace(/_/gm,'.')+'$','gim').test(value)){"
		if (StringUtils.isEmpty(str)) {
    		return false;
    	}
		
		parttern = escapeRegex(parttern);
		
		parttern = parttern.replaceAll("%+", ".*").replaceAll("_", ".");
		Boolean match = Pattern.compile(parttern, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE).matcher(str).find();
		
		return match;
	}
	
	/**
  	 * 清除末尾的逗号
  	 * @param FIELDS_SPLIT_STR
  	 * @return
  	 */
  	public static String trimSplitChar(String FIELDS_SPLIT_STR) {
  		return trimSplitChar(FIELDS_SPLIT_STR,",");
  	}
	public static String trimSplitChar(String FIELDS_SPLIT_STR,String splitChar) {
  		if(FIELDS_SPLIT_STR.endsWith(splitChar)) {
			FIELDS_SPLIT_STR=FIELDS_SPLIT_STR.substring(0,FIELDS_SPLIT_STR.length()-splitChar.length());
		}
  		return FIELDS_SPLIT_STR;
  	}

	public static List<String> strToStrList(String str) {
		List<String> list = null;
		if(!StringUtils.isEmpty(str)) {
			list = Arrays.asList(str.split(","));
		}
		return list;
	}
}